package com.meter.rabbitmq.service;

import com.meter.common.utils.uuid.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnsCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class RabbitService implements ConfirmCallback, ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送mq消息 工作队列模式
     * @param routingKey
     * @param object
     * @throws InterruptedException
     */
    public void sendWorkQueue(String routingKey, Object object){
        //这是设置回调能收到的发送到响应
        rabbitTemplate.setConfirmCallback(this);
        //如果设置备份队列，则不起作用
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback(this);
        String messageId = IdUtils.fastUUID();
        CorrelationData correlationData = new CorrelationData(messageId);
        rabbitTemplate.convertAndSend(routingKey, object, correlationData);
    }

    /**
     * 发送mq消息 广播模式
     * @param exchange
     * @param object
     */
    public void sendFanout(String exchange, Object object){
        //这是设置回调能收到的发送到响应
        rabbitTemplate.setConfirmCallback(this);
        //如果设置备份队列，则不起作用
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback(this);
        String messageId = IdUtils.fastUUID();
        CorrelationData correlationData = new CorrelationData(messageId);
        rabbitTemplate.convertAndSend(exchange, "", object, correlationData);
    }

    /**
     * 发送mq消息 路由模式
     * @param exchange
     * @param routingKey 路由key
     * @param object
     */
    public void sendDirect(String exchange, String routingKey, Object object){
        //这是设置回调能收到的发送到响应
        rabbitTemplate.setConfirmCallback(this);
        //如果设置备份队列，则不起作用
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback(this);
        String messageId = IdUtils.fastUUID();
        CorrelationData correlationData = new CorrelationData(messageId);
        rabbitTemplate.convertAndSend(exchange, routingKey, object, correlationData);
    }

    /**
     * 发送mq消息 通配符模式
     * @param exchange
     * @param routingKey 通配符
     * @param object
     */
    public void sendTopics(String exchange, String routingKey, Object object){
        //这是设置回调能收到的发送到响应
        rabbitTemplate.setConfirmCallback(this);
        //如果设置备份队列，则不起作用
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback(this);
        String messageId = IdUtils.fastUUID();
        CorrelationData correlationData = new CorrelationData(messageId);
        rabbitTemplate.convertAndSend(exchange, routingKey, object, correlationData);
    }

    /**
     * 消息确认回调
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(!ack){
            log.info("消息发送失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
        }
    }

    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",returnedMessage.getExchange(),returnedMessage.getRoutingKey(),returnedMessage.getReplyCode(),returnedMessage.getReplyText(),returnedMessage.getMessage());
    }

}
